package com.jdrx.ocp.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.jdrx.ocp.beans.dto.platform.CreatePlatformApiByListDTO;
import com.jdrx.ocp.beans.dto.platform.CreatePlatformApiDTO;
import com.jdrx.ocp.beans.dto.platform.ExportPlatformApiDTO;
import com.jdrx.ocp.beans.dto.platform.QueryPlatformPrefixDTO;
import com.jdrx.ocp.beans.entity.PlatformApiPO;
import com.jdrx.ocp.beans.entity.PlatformPO;
import com.jdrx.ocp.beans.entity.util.KeyValue;
import com.jdrx.ocp.beans.vo.QueryPlatformApiAuthVO;
import com.jdrx.ocp.beans.vo.excel.ExcelApiVO;
import com.jdrx.ocp.beans.vo.excel.ExcelServiceVO;
import com.jdrx.ocp.config.DesConfig;
import com.jdrx.ocp.dao.PlatformApiDAO;
import com.jdrx.ocp.utils.Convertor;
import com.jdrx.ocp.utils.CreateZip;
import com.jdrx.platform.commons.rest.beans.enums.EApiStatus;
import com.jdrx.platform.commons.rest.beans.vo.ResposeVO;
import com.jdrx.platform.commons.rest.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import retrofit2.Call;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName:PlatformApiService
 * @Description:平台API权限管理模块接口
 * @author: yangfang
 * @date: 2018/11/19 13:41
 */
@Service
public class PlatformApiService {
    private static final Logger logger = LoggerFactory.getLogger(PlatformApiService.class);
    @Autowired
    private PlatformApiDAO platformApiDAO;
    //@Autowired
    //private ProjectGateWayService gateWayService;
    @Autowired
    private DesConfig desConfig;
    @Autowired
    private PlatformService platformService;

    /**
     * 创建平台-API授权信息
     * @param dto
     * @throws BizException
     */
    @Transactional(rollbackFor = Exception.class)
    public void createPlatformApiAuth(CreatePlatformApiDTO dto) throws BizException{
        try {
            //根据平台前缀删除 平台-API关系
            platformApiDAO.deleteByPrefix(new PlatformApiPO(dto.getPlatformPrefix()));

            List<String> apiUris = Convertor.conver(dto.getApiUris());
            if(CollectionUtils.isEmpty(apiUris)){
                return;
            }

            List<PlatformApiPO> datas = new ArrayList<PlatformApiPO>();
            for(String api : apiUris){
                PlatformApiPO po = new PlatformApiPO();
                po.setPlatformPrefix(dto.getPlatformPrefix());
                po.setApiUri(api);
                datas.add(po);
            }

            if(!CollectionUtils.isEmpty(datas)){
                platformApiDAO.insertList(datas);
            }
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("创建数据失败！");
        }
    }

    /**
     * 创建平台-API授权信息-数组结构
     * @param dto
     * @throws BizException
     */
    @Transactional(rollbackFor = Exception.class)
    public void createPlatformApiAuth(CreatePlatformApiByListDTO dto) throws BizException{
        try {
            //根据平台前缀删除 平台-API关系
            List<KeyValue> list = dto.getList();
            if(list != null && list.size() > 0) {
                String targetPrefix = list.get(0).getKey();
                PlatformApiPO platformApiPO = new PlatformApiPO();
                platformApiPO.setPlatformPrefix(dto.getPlatformPrefix());
                platformApiPO.setTargetPlatformPrefix(targetPrefix);
                platformApiDAO.deleteByPrefix(platformApiPO);
            }

            List<KeyValue> apiUris = dto.getList();
            if(CollectionUtils.isEmpty(apiUris)){
                return;
            }

            List<PlatformApiPO> datas = new ArrayList<PlatformApiPO>();
            for(KeyValue api : apiUris){
                PlatformApiPO po = new PlatformApiPO();
                po.setPlatformPrefix(dto.getPlatformPrefix());
                po.setApiUri(api.getValue());
                po.setTargetPlatformPrefix(api.getKey());
                datas.add(po);
            }

            if(!CollectionUtils.isEmpty(datas)){
                platformApiDAO.insertList(datas);
            }
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("创建数据失败！");
        }
    }

    /**
     * 查询平台-API授权关系数据
     * @param token
     * @return
     * @throws BizException
     */
    public List<QueryPlatformApiAuthVO> queryPlatformApiAuth (String token, QueryPlatformPrefixDTO dto) throws BizException{
        try {
            List<QueryPlatformApiAuthVO> datas = new ArrayList<QueryPlatformApiAuthVO>();
            //查询所有的接口
//            List<Map<String, Object>> apis = getApis(token, null);
            //查询指定平台API
            List<Map<String, Object>> apis = getApis(token, dto.getTargetPrefix());
            List<PlatformApiPO> platformApis = platformApiDAO.listByCondition(new PlatformApiPO(dto.getPrefix()));
            for(Map<String, Object> map : apis){
                QueryPlatformApiAuthVO vo = new QueryPlatformApiAuthVO();
                vo.setPlatformId(Long.valueOf(String.valueOf(map.get("serviceId"))));
                vo.setPlatformName(String.valueOf(map.get("serviceName")));
                vo.setPlatformPrefix(String.valueOf(map.get("servicePrefix")));
                vo.setApiName(String.valueOf(map.get("apiName")));
                vo.setApiUri(String.valueOf(map.get("apiUri")));
                vo.setModelName(String.valueOf(map.get("modelName")));

                if(!CollectionUtils.isEmpty(platformApis)){
                    for(PlatformApiPO po : platformApis){
                        if(String.valueOf(map.get("apiUri")).equals(po.getApiUri())){
                            vo.setAuth(true);
                        }
                    }
                }
                datas.add(vo);
            }
            return datas;
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 获取平台服务已授权api的统计信息
     * @return
     * @throws BizException
     */
    public List<Map<String,Object>> queryPlatformAuth() throws BizException {
        try{
            return platformApiDAO.queryPlatformAuth();
        }catch (Exception e){
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 远程调用API接口数据
     * @param token
     * @return
     * @throws BizException
     */
    public List<Map<String, Object>> getApis(String token, String prefix) throws BizException{
        try {
            Map<String, Object> map = new HashMap<>();
            if(StringUtils.isNotBlank(prefix)){
                map.put("servicePrefix", prefix);
            }
            Call<ResposeVO> resposeVOCall =  null;
            ResposeVO resposeVO = new ResposeVO();
            try {
                resposeVO = resposeVOCall.execute().body();
            }catch (Exception e){
                logger.error(e.getMessage(), e);
                throw new BizException(e.getMessage());
            }
            if( !resposeVO.getStatus().equals(EApiStatus.SUCCESS.getStatus()) ){
                throw new BizException(resposeVO.getMessage());
            }
            List<Map<String, Object>> dataMap = (List<Map<String,Object>>) resposeVO.getData();
            return dataMap;
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 远程调用API服务数据
     * @param token
     * @return
     * @throws BizException
     */
    public List<Map<String, Object>> getServices(String token, ExportPlatformApiDTO dto) throws BizException{
        try {
            Map<String, Object> map = new HashMap<>();
//            map.put("apiName", dto.getName());
//            map.put("setvicePrefix", dto.getPrefix());
            Call<ResposeVO> resposeVOCall =  null;
            ResposeVO resposeVO = new ResposeVO();
            try {
                resposeVO = resposeVOCall.execute().body();
            }catch (Exception e){
                logger.error(e.getMessage(), e);
                throw new BizException(e.getMessage());
            }
            if( !resposeVO.getStatus().equals(EApiStatus.SUCCESS.getStatus()) ){
                throw new BizException(resposeVO.getMessage());
            }
            List<Map<String, Object>> dataMap = (List<Map<String,Object>>) resposeVO.getData();
            return dataMap;
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 远程调用API接口获取统计数据
     * @param token
     * @return
     * @throws BizException
     */
    public Map<String, Object> getStatisticNum(String token, List<String> prefixs) throws BizException{
        try {
            Map<String, Object> map = new HashMap<>();
            if(prefixs != null && prefixs.size() > 0){
                map.put("prefixs", prefixs);
            }
            Call<ResposeVO> resposeVOCall =  null;
            ResposeVO resposeVO = new ResposeVO();
            try {
                resposeVO = resposeVOCall.execute().body();
            }catch (Exception e){
                logger.error(e.getMessage(), e);
                throw new BizException(e.getMessage());
            }
            if( !resposeVO.getStatus().equals(EApiStatus.SUCCESS.getStatus()) ){
                throw new BizException(resposeVO.getMessage());
            }
            return (Map<String, Object>) resposeVO.getData();
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("获取统计数据失败！");
        }
    }

    /**
     * 导出平台API
     * @param dto 查询条件
     * @param response response流
     */
    public void exportPlatformApi(ExportPlatformApiDTO dto, String token, String userId, HttpServletResponse response) throws BizException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/zip");
        // filename指定默认的名字
        response.addHeader("Content-Disposition", "attachment;filename=apiService_"+ System.currentTimeMillis() +".zip");
        InputStream in = null;
        OutputStream os = null;
        try {
            String fileUrl = exportPlatformApiData(dto, token, userId);
            logger.info("下载文件地址的：" + fileUrl);
            in = new FileInputStream(fileUrl);
            int len = 0;
            byte[] buffer = new byte[1024];
            os = response.getOutputStream();
            while((len=in.read(buffer))>0){
                os.write(buffer,0,len);
            }
            //8.关闭流
            in.close();
            os.close();
            //删除历史文件
            File file=new File(fileUrl);
            if(file.exists()&&file.isFile()) {
                file.delete();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }finally {
            try {
                if(in != null){
                    in.close();
                }
                if(os != null){
                    os.close();
                }
            }catch (Exception e){
                logger.error(e.getMessage(), e);
                throw new BizException("获取数据失败！");
            }
        }
    }

    /**
     * 获取Excel服务列表数据
     * @param token
     * @param queryServiceDTO
     * @return
     * @throws BizException
     */
    private List<ExcelServiceVO> getExcelServices(String token, ExportPlatformApiDTO queryServiceDTO) throws BizException{
        try {
            List<ExcelServiceVO> serviceList = new ArrayList<ExcelServiceVO>();
            //查询服务列表
            List<Map<String, Object>> apiCenterServiceData = getServices(token, queryServiceDTO);
            Map<String,Long> servicePrefixId = new HashMap<>();
            apiCenterServiceData.forEach(map -> {
                servicePrefixId.put(String.valueOf(map.get("servicePrefix")),Long.valueOf(String.valueOf(map.get("id"))));
            });
            List<PlatformPO> serviceData = platformService.getPlatform();
            if(CollectionUtils.isEmpty(serviceData)){
                return serviceList;
            }
            for(PlatformPO po : serviceData){
                ExcelServiceVO vo = new ExcelServiceVO();
//                vo.setId(Optional.ofNullable(servicePrefixId.get(po.getPrefix())).orElse(po.getId()));
                vo.setId(po.getId());
                vo.setServiceName(po.getName());
                vo.setServicePrefix(po.getName());
                vo.setApplicationName(po.getName());
                vo.setServiceUrl(po.getServerAddress());
                vo.setCallBackUrl(po.getCallBackAddress());
                vo.setProvideServiceName(po.getName());
                vo.setInfoDescription(po.getRemark());
                vo.setPlatformId("");
                vo.setPlatformVersion("1.0.0");
                vo.setServiceFlag(0);
                vo.setApiType(po.getServiceType());
                vo.setModelNum(0);
                serviceList.add(vo);
            }
            return serviceList;
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 获取ExcelAPI列表数据
     * @param token
     * @param queryServiceDTO
     * @return
     * @throws BizException
     */
    private List<ExcelApiVO> getExcelApis(String token, ExportPlatformApiDTO queryServiceDTO) throws BizException{
        try {
            List<ExcelApiVO> apiList = new ArrayList<ExcelApiVO>();
            //查询API列表
            List<Map<String, Object>> apiData = getApis(token, queryServiceDTO.getPrefix());
            if(CollectionUtils.isEmpty(apiData)){
                return apiList;
            }
            for(Map<String, Object> map : apiData){
                ExcelApiVO vo = new ExcelApiVO();
                vo.setId(map.get("id") == null ? null : String.valueOf(map.get("id")));
                vo.setServiceId(map.get("serviceId") == null ? null : Long.valueOf(String.valueOf(map.get("serviceId"))));
                vo.setApiName(map.get("apiName") == null ? null : String.valueOf(map.get("apiName")));
                vo.setApiUri(map.get("apiUri") == null ? null : String.valueOf(map.get("apiUri")));
                vo.setApiDescription(map.get("apiDescription") == null ? null : String.valueOf(map.get("apiDescription")));
                vo.setModelName(map.get("modelName") == null ? null : String.valueOf(map.get("modelName")));
                vo.setProtocol(map.get("protocol") == null ? null : String.valueOf(map.get("protocol")));
                vo.setRemarks(map.get("remarks") == null ? null : String.valueOf(map.get("remarks")));
                vo.setHeader(map.get("header") == null ? null : String.valueOf(map.get("header")));
                List<Map<String, Object>> apiParameters = (List<Map<String, Object>>) map.get("requestParameters");
//                vo.setApiParameters(CollectionUtils.isEmpty(apiParameters) ? null : JSONArray.fromObject(apiParameters).toString());
                vo.setApiParameters(CollectionUtils.isEmpty(apiParameters) ? null : JSON.toJSONString(apiParameters));
                List<Map<String, Object>> outParameters = (List<Map<String, Object>>) map.get("responseParameters");
                vo.setOutParameters(CollectionUtils.isEmpty(outParameters) ? null : JSON.toJSONString(outParameters));
                apiList.add(vo);
            }
            return apiList;
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            throw new BizException("获取数据失败！");
        }
    }

    /**
     * 导出平台-API数据
     * @param queryServiceDTO
     * @param token
     * @return
     * @throws BizException
     */
    public String exportPlatformApiData(ExportPlatformApiDTO queryServiceDTO, String token, String userId) throws BizException {
        try {
            //查询服务列表
            List<ExcelServiceVO> serviceList = getExcelServices(token, queryServiceDTO);
            //查询API列表
            List<ExcelApiVO> apiList = getExcelApis(token, queryServiceDTO);
            //写入服务数据
            JSONArray jsonArrayService = JSON.parseArray(JSON.toJSONString(serviceList));
            writerFile(desConfig.getExportApiFileUrl()+"/api_interface_files/js/data/menu.js","var serverList="+jsonArrayService.toString());
            //写入接口数据
            JSONArray jsonArrayApi = JSON.parseArray(JSON.toJSONString(apiList));
            writerFile(desConfig.getExportApiFileUrl()+"/api_interface_files/js/data/data.js","var datainfo="+jsonArrayApi.toString());
            //文件存储路径
            String fileUrl = desConfig.getExportApiFileUrl()+"/api_data_"+userId+".zip";
            //生成zip文件
            CreateZip.createZip(desConfig.getExportApiFileUrl()+"/api_interface_files", fileUrl);
            //清空历史数据
            writerFile(desConfig.getExportApiFileUrl()+"/api_interface_files/js/data/menu.js","var serverList=[{}]");
            writerFile(desConfig.getExportApiFileUrl()+"/api_interface_files/js/data/data.js","var datainfo=[{}]");
            return fileUrl;
        } catch (Exception e) {
            logger.error("查询数据异常" + queryServiceDTO, e);
            throw new BizException("导出异常，请稍后重试");
        }
    }

    /**
     * 写文件数据
     * @param filePath
     * @param wirterData
     * @throws IOException
     */
    public void writerFile(String filePath, String wirterData) throws IOException {
        logger.info("文件目录：" + filePath);
        FileWriter fw = null;
        File f = new File(filePath);
        BufferedWriter out = null;
        try {
            if (!f.exists()) {
                f.createNewFile();
            }
            fw = new FileWriter(f);
            out = new BufferedWriter(fw);
            out.write(wirterData, 0, wirterData.length());

        } catch (IOException e) {
            throw e;
        }finally {
            if(out != null) {
                out.close();
            }
        }
    }

    /**
     * 服务及授权二维表数据
     * @param token
     * @return
     * @throws BizException
     */
    public List<Map<String,Object>> platformAuth(String token) throws BizException {
        try{
//            List<Map<String,Object>> services = getServices(token, new ExportPlatformApiDTO());
            List<PlatformPO> platformPOList = platformService.getPlatform();
            List<Map<String,Object>> services = new ArrayList<>();
            platformPOList.forEach(platformPO -> {
                Map<String,Object> map = new HashMap<>();
                map.put("id",platformPO.getId());
                map.put("servicePrefix",platformPO.getPrefix());
                map.put("serviceName",platformPO.getName());
                services.add(map);
            });
            if(services != null && services.size() > 0) {
                List<Map<String, Object>> auths = queryPlatformAuth();
                for(Map<String,Object> map : services){
                    List<Integer> items = new ArrayList<>();
                    for(Map<String,Object> map2 : services){
                        int thisNum = 0;
                        for(Map<String,Object> map3 : auths){
                            if(map.get("servicePrefix").toString().equals(map3.get("platform_prefix").toString()) &&
                                    map2.get("servicePrefix").toString().equals(map3.get("target_platform_prefix").toString())
                                    ){
                                thisNum = Integer.valueOf(map3.get("number").toString());
                                break;
                            }
                        }
                        items.add(thisNum);
                    }
                    map.put("items",items);
                }
            }
            return services;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            throw new BizException("获取数据失败！");
        }
    }

}
